home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / mach / sun4c.md / machCode.c < prev    next >
C/C++ Source or Header  |  1991-08-13  |  65KB  |  2,080 lines

  1. /* 
  2.  * machCode.c --
  3.  *
  4.  *     C code for the mach module.
  5.  *
  6.  * Copyright (C) 1985 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /sprite/src/kernel/mach/sun4.md/RCS/machCode.c,v 9.34 91/08/12 22:15:28 shirriff Exp $ SPRITE (Berkeley)";
  12. #endif /* not lint */
  13.  
  14. #include <stddef.h>
  15. #include <sprite.h>
  16. #include <swapBuffer.h>
  17. #include <machConst.h>
  18. #include <machMon.h>
  19. #include <machInt.h>
  20. #include <mach.h>
  21. #include <proc.h>
  22. #include <prof.h>
  23. #include <sys.h>
  24. #include <sched.h>
  25. #include <vm.h>
  26. #include <vmMach.h>
  27. #include <user/sun4.md/sys/machSignal.h>
  28. #include <procUnixStubs.h>
  29.  
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #include <bstring.h>
  33. #include <compatInt.h>
  34. /*
  35.  *  Number of processors in the system.
  36.  */
  37. #ifndef NUM_PROCESSORS
  38. #define NUM_PROCESSORS 1
  39. #endif NUM_PROCESSORS
  40.  
  41. int mach_NumProcessors = NUM_PROCESSORS;
  42. int    storedDataSize = -1;    /* Not initialized. */
  43.  
  44. /*
  45.  * TRUE if cpu was in kernel mode before the interrupt, FALSE if was in 
  46.  * user mode.
  47.  */
  48. Boolean    mach_KernelMode;
  49.  
  50. /*
  51.  * Sp saved into this before debugger call.
  52.  */
  53. int    machSavedRegisterState = 0;
  54.  
  55. /*
  56.  *  Flag used by routines to determine if they are running at
  57.  *  interrupt level.
  58.  */
  59. Boolean mach_AtInterruptLevel = FALSE;
  60.  
  61. /*
  62.  * The machine type string is imported by the file system and
  63.  * used when expanding $MACHINE in file names.
  64.  */
  65.  
  66. char *mach_MachineType = "sun4";
  67.  
  68. /*
  69.  * The byte ordering/alignment type used with Fmt_Convert and I/O control data.
  70.  * For compatablity we set this to the old Swap_Buffer constant.
  71.  */
  72. Fmt_Format    mach_Format = FMT_SPARC_FORMAT;
  73.  
  74. /*
  75.  *  Count of number of ``calls'' to enable interrupts minus number of calls
  76.  *  to disable interrupts.  Kept on a per-processor basis.
  77.  */
  78. int mach_NumDisableInterrupts[NUM_PROCESSORS];
  79. int *mach_NumDisableIntrsPtr = mach_NumDisableInterrupts;
  80.  
  81. extern int debugProcStubs;
  82.  
  83. /*
  84.  * Machine dependent variables.
  85.  */
  86. Address    mach_KernStart;
  87. Address    mach_CodeStart;
  88. Address    mach_StackBottom;
  89. int    mach_KernStackSize;
  90. Address    mach_KernEnd;
  91. Address    mach_FirstUserAddr;
  92. Address    mach_LastUserAddr;
  93. Address    mach_MaxUserStackAddr;
  94. int    mach_LastUserStackPage;
  95.  
  96. Address    machTBRAddr;            /* address of trap table.  The value
  97.                      * is set up and stored here in
  98.                      * bootSysAsm.s.*/
  99. #define    MACH_NUM_VECTORS    256    /* Number of interrupt vector slots */
  100. Address    machVectorTable[MACH_NUM_VECTORS];    /* Table of autovector and
  101.                      * vectored interrupt handlers. */
  102. ClientData    machInterruptArgs[MACH_NUM_VECTORS];    /* Table of clientData
  103.                      * args to pass interrupt handlers */
  104. int    machMaxSysCall;            /* Hightest defined system call. */
  105. int    machArgOffsets[SYS_NUM_SYSCALLS];/* For each system call, tells how
  106.                      * much to add to the fp at the time
  107.                      * of the call to get to the highest
  108.                      * argument on the stack.  */
  109. Address    machArgDispatch[SYS_NUM_SYSCALLS];/* For each system call, gives an
  110.                      * address to branch to, in the
  111.                      * middle of MachFetchArgs, to copy the
  112.                      * right # of args from user space to
  113.                      * the kernel's stack. */
  114. ReturnStatus    (*(mach_NormalHandlers[SYS_NUM_SYSCALLS]))();
  115.                     /* For each system call, gives the
  116.                      * address of the routine to handle
  117.                      * the call for non-migrated processes.
  118.                          */
  119. ReturnStatus (*(mach_MigratedHandlers[SYS_NUM_SYSCALLS]))();
  120.                     /* For each system call, gives the
  121.                      * address of the routine to handle
  122.                          * the call for migrated processes. */
  123. int    machKcallTableOffset;        /* Byte offset of the kcallTable field
  124.                      * in a Proc_ControlBlock. */
  125. int    machStatePtrOffset;        /* Byte offset of the machStatePtr
  126.                      * field in a Proc_ControlBlock. */
  127. int    machSpecialHandlingOffset;    /* Byte offset of the specialHandling
  128.                      * field in a Proc_ControlBlock. */
  129. int    machTmpRegsOffset;        /* Offset of overflow temp regs. */
  130. int    machTmpRegsStore[2];        /* Temporary storage. */
  131. int    machGenFlagsOffset;        /* offset of genFlags field in a
  132.                      * Proc_ControlBlock. */
  133. int    machForeignFlag;        /* Value of PROC_FOREIGN available
  134.                      * in assembler. */
  135. int    MachPIDOffset;            /* Byte offset of pid in PCB */
  136. char    mach_DebugStack[0x2000];    /* The debugger stack. */
  137. unsigned int    machDebugStackStart;    /* Contains address of base of debugger
  138.                      * stack. */
  139. int    machSignalStackSizeOnStack;    /* size of mach module sig stack */
  140. int    machSigStackSize;        /* size of Sig_Stack structure */
  141. int    machSigStackOffsetOnStack;    /* offset of sigStack field in
  142.                      * MachSignalStack structure on the
  143.                      * the user stack. */
  144. int    machSigStackOffsetInMach;    /* offset to sigStack field in mach
  145.                      * state structure. */
  146. int    machSigContextSize;        /* size of Sig_Context structure */
  147. int    machSigContextOffsetOnStack;    /* offset of sigContext field in
  148.                      * MachSignalStack structure on the
  149.                      * user stack. */
  150. int    machSigContextOffsetInMach;    /* offset to sigContext field in mach
  151.                      * state structure. */
  152. int    machSigUserStateOffsetOnStack;    /* offset of machine-dependent field
  153.                      * on the stack, called machContext,
  154.                      * in the Sig_Context part of the
  155.                      * MachSignalStack structure. */
  156. int    machSigTrapInstOffsetOnStack;    /* offset of trapInst field in
  157.                      * MachSignalStack on user stack. */
  158. int    machSigNumOffsetInSig;        /* offset of sigNum field in
  159.                      * Sig_Stack structure. */
  160. int    machSigAddrOffsetInSig;        /* offset of sigAddr field in
  161.                      * Sig_Stack structure. */
  162. int    machSigCodeOffsetInSig;        /* offset of sigCode field in
  163.                      * Sig_Stack structure. */
  164. int    machSigPCOffsetOnStack;        /* offset of pcValue field in
  165.                      * MachSignalStack on user stack. */
  166. int    machLastSysCallOffset;        /* offset of lastSysCall field in
  167.                      * Mach_State structure. */
  168.  
  169.  
  170. Proc_ControlBlock *machFPUSaveProcPtr;    /* Set to the Proc_ControlBlock of the
  171.                      * process we are saving the FPU
  172.                      * state for in Mach_Context switch. */
  173. int        machFPUSyncInst();     /* PC of stfsr instruction in 
  174.                     * context switch. */
  175. int        machFPUDumpSyncInst(); /* PC of stfsr instruction in 
  176.                     * MachDumpFPUState. */
  177. /*
  178.  * Pointer to the state structure for the current process.
  179.  */
  180. Mach_State    *machCurStatePtr = (Mach_State *)NIL;
  181.  
  182. char    MachUnixAddr[] =
  183.                 "Unix addr %x\n"; 
  184. char    MachUnixString[] =
  185.                 "Unix syscall %d\n"; 
  186. char    MachUnixYesString[] =
  187.                 "syscall success\n"; 
  188. char    MachUnixNoString[] =
  189.                 "syscall failure\n"; 
  190. char    MachRunUserDeathString[] =
  191.                 "MachRunUserProc: killing process!\n"; 
  192. char    MachHandleSignalDeathString[] =
  193.                 "MachHandleSignal: killing process!\n"; 
  194. char    MachReturnFromSignalDeathString[] =
  195.                 "MachReturnFromSignal: killing process!\n"; 
  196. char    MachReturnFromTrapDeathString[] =
  197.                 "MachReturnFromTrap: killing process!\n"; 
  198. char    MachHandleWindowUnderflowDeathString[] =
  199.                 "MachHandleWindowUnderflow: killing process!\n";
  200.  
  201. /*
  202.  * For testing correctness of defined offsets.
  203.  */
  204. #if 0
  205. Mach_RegState        testMachRegState;
  206. Mach_State        testMachState;
  207. Proc_ControlBlock    testPCB;
  208. MachSignalStack        testSignalStack;
  209. Sig_Context        testContext;
  210. Sig_Stack        testStack;
  211. #endif
  212. int            debugCounter = 0;        /* for debugging */
  213. int            debugSpace[500];
  214. Address            theAddrOfVmPtr = 0; 
  215. Address            theAddrOfMachPtr = 0;
  216. Address            oldAddrOfVmPtr = 0; 
  217. Address            oldAddrOfMachPtr = 0;
  218.  
  219. Address            machRomVectorPtr;
  220. MachMonBootParam    machMonBootParam;
  221.  
  222. /*
  223.  * Forward declarations.
  224.  */
  225. static void FlushTheWindows _ARGS_((int num));
  226. static void HandleFPUException _ARGS_((Proc_ControlBlock *procPtr, 
  227.                        Mach_State *machStatePtr));
  228.  
  229.  
  230.  
  231. /*
  232.  * ----------------------------------------------------------------------------
  233.  *
  234.  * Mach_Init --
  235.  *
  236.  *    Initialize some stuff.
  237.  *
  238.  * Results:
  239.  *    None.
  240.  *
  241.  * Side effects:
  242.  *    None.
  243.  *
  244.  * ----------------------------------------------------------------------------
  245.  */
  246. void
  247. Mach_Init()
  248. {
  249.     int        i;
  250.     extern    void    MachVectoredInterrupt();
  251.     extern    void    MachHandleDebugTrap();
  252.     int        offset;
  253.  
  254.     /*
  255.      * Set exported machine dependent variables.
  256.      */
  257.     mach_KernStart = (Address)MACH_KERN_START;
  258.     mach_KernEnd = (Address)MACH_KERN_END;
  259.     mach_CodeStart = (Address)MACH_CODE_START;
  260.     mach_StackBottom = (Address)MACH_STACK_BOTTOM;
  261.     mach_KernStackSize = MACH_KERN_STACK_SIZE;
  262.     mach_FirstUserAddr = (Address)MACH_FIRST_USER_ADDR;
  263.     mach_LastUserAddr = (Address)MACH_LAST_USER_ADDR;
  264.     mach_MaxUserStackAddr = (Address)MACH_MAX_USER_STACK_ADDR;
  265.     mach_LastUserStackPage = (MACH_MAX_USER_STACK_ADDR - 1) / VMMACH_PAGE_SIZE;
  266.  
  267. #define    CHECK_SIZE(c, d)        \
  268.     if (sizeof (c) != d) {        \
  269.     panic("Bad size for structure.  Redo machConst.h!\n");\
  270.     }
  271.     
  272. #define    CHECK_OFFSETS(s, o)        \
  273.     if (offsetof(Mach_State, s) != o) { \
  274.     panic("Bad offset for registers.  Redo machConst.h!\n");\
  275.     }
  276. #define    CHECK_TRAP_REG_OFFSETS(s, o)       \
  277.     if (offsetof(Mach_RegState, s) != o) { \
  278.     panic("Bad offset for trap registers.  Redo machConst.h!\n");\
  279.     }
  280.  
  281.  
  282.     CHECK_SIZE(Mach_RegState, MACH_SAVED_STATE_FRAME);
  283.     CHECK_OFFSETS(trapRegs, MACH_TRAP_REGS_OFFSET);
  284.     CHECK_OFFSETS(switchRegs, MACH_SWITCH_REGS_OFFSET);
  285.     CHECK_OFFSETS(savedRegs[0][0], MACH_SAVED_REGS_OFFSET);
  286.     CHECK_OFFSETS(savedMask, MACH_SAVED_MASK_OFFSET);
  287.     CHECK_OFFSETS(savedSps[0], MACH_SAVED_SPS_OFFSET);
  288.     CHECK_OFFSETS(kernStackStart, MACH_KSP_OFFSET);
  289.     CHECK_OFFSETS(fpuStatus, MACH_FPU_STATUS_OFFSET)
  290.     CHECK_TRAP_REG_OFFSETS(curPsr, MACH_LOCALS_OFFSET);
  291.     CHECK_TRAP_REG_OFFSETS(ins[0], MACH_INS_OFFSET);
  292.     CHECK_TRAP_REG_OFFSETS(globals[0], MACH_GLOBALS_OFFSET);
  293.     CHECK_TRAP_REG_OFFSETS(fsr, MACH_FPU_FSR_OFFSET);
  294.     CHECK_TRAP_REG_OFFSETS(numQueueEntries, MACH_FPU_QUEUE_COUNT);
  295.     CHECK_TRAP_REG_OFFSETS(fregs, MACH_FPU_REGS_OFFSET);
  296.     CHECK_TRAP_REG_OFFSETS(fqueue, MACH_FPU_QUEUE_OFFSET);
  297.  
  298. #ifdef sun4c
  299.     if ((*(romVectorPtr->virtMemory))->address !=
  300.         (unsigned) VMMACH_DEV_START_ADDR ||
  301.         ((unsigned) VMMACH_DEV_START_ADDR +
  302.         (*(romVectorPtr->virtMemory))->size - 1)
  303.         != (unsigned) VMMACH_DEV_END_ADDR) {
  304.     panic("VMMACH_DEV_START_ADDR and VMMACH_DEV_END_ADDR are wrong.\n");
  305.     }
  306. #endif /* sun4c */
  307. #undef CHECK_SIZE
  308. #undef CHECK_OFFSETS
  309.     /*
  310.      * Initialize some of the dispatching information.  The rest is initialized
  311.      * by Mach_InitSysCall, below.
  312.      */
  313.  
  314.     /*
  315.      * Get offset of machStatePtr in proc control blocks.  This one is
  316.      * subject to a different module, so it's easier not to use a constant.
  317.      */
  318.     machStatePtrOffset = offsetof(Proc_ControlBlock, machStatePtr);
  319.     machKcallTableOffset = offsetof(Proc_ControlBlock, kcallTable);
  320.     machSpecialHandlingOffset = offsetof(Proc_ControlBlock, specialHandling);
  321.  
  322.     if (MACH_UNIX_ERRNO_OFFSET != offsetof(Proc_ControlBlock, unixErrno)) {
  323.     panic("MACH_UNIX_ERRNO_OFFSET is wrong!\n");
  324.     }
  325.  
  326.     machMaxSysCall = -1;
  327.     MachPIDOffset = offsetof(Proc_ControlBlock, processID);
  328.     machGenFlagsOffset = offsetof(Proc_ControlBlock, genFlags);
  329.     machForeignFlag = PROC_FOREIGN;
  330.  
  331.     /*
  332.      * Initialize all the horrid offsets for dealing with getting stuff from
  333.      * signal things in the mach state structure to signal things on the user
  334.      * stack.
  335.      */
  336.     machSignalStackSizeOnStack = sizeof (MachSignalStack);
  337.     if ((machSignalStackSizeOnStack & 0x7) != 0) {
  338.     panic("MachSignalStack struct must be a multiple of double-words!\n");
  339.     }
  340.  
  341.     machSigStackSize = sizeof (Sig_Stack);
  342.     machSigStackOffsetOnStack = offsetof(MachSignalStack, sigStack);
  343.     machSigStackOffsetInMach = offsetof(Mach_State, sigStack);  
  344.     machSigContextSize = sizeof (Sig_Context);
  345.     machSigContextOffsetOnStack = offsetof(MachSignalStack, sigContext);
  346.     machSigContextOffsetInMach = offsetof(Mach_State, sigContext);
  347.     machSigUserStateOffsetOnStack = offsetof(MachSignalStack, 
  348.         sigContext.machContext.userState);
  349.     machSigTrapInstOffsetOnStack = offsetof(MachSignalStack,
  350.         sigContext.machContext.trapInst);
  351.     machSigNumOffsetInSig = offsetof(Sig_Stack, sigNum);
  352.     machSigAddrOffsetInSig = offsetof(Sig_Stack, sigAddr);
  353.     machSigCodeOffsetInSig = offsetof(Sig_Stack, sigCode);
  354.     machSigPCOffsetOnStack = offsetof(MachSignalStack, 
  355.         sigContext.machContext.pcValue);
  356.  
  357.     machLastSysCallOffset = offsetof(Mach_State, lastSysCall);
  358.  
  359.     /*
  360.      * base of the debugger stack
  361.      */
  362.     machDebugStackStart = (unsigned int) mach_DebugStack +
  363.                         sizeof (mach_DebugStack);
  364.  
  365.     /*
  366.      * Initialize the interrupt vector table.
  367.      */
  368.     for (i = 0; i < MACH_NUM_VECTORS; i++) {
  369. #ifndef sun4c
  370.     if (i == 13 || i == 11 || i == 9 || i == 7 || i == 5 || i == 3 ||
  371.         i == 2) {
  372.         machVectorTable[i] = (Address) MachVectoredInterrupt;
  373.         /*
  374.          * Set arg to vme vector address for this trap level.
  375.          * In the high bits of the address, we want MACH_VME_INTR_VECTOR.
  376.          * In bits 3 to 1 we want the VME bus level.  We want bit 0 to be
  377.          * 1.  So, for example, for interrupt level 13, we want to put
  378.          * VME level7 into bits 3 to 1 and then set bit 0 high.  But this
  379.          * is equivalent to putting the number 14 into bits 3 to 0 and then
  380.          * setting bit 0 high.  So this means adding 1 to the interrupt
  381.          * level and then setting bit 0 high.
  382.          */
  383.         machInterruptArgs[i] = (ClientData)
  384.             (MACH_VME_INTR_VECTOR | ((i + 1) | 1));
  385.     } else { 
  386. #endif
  387.         machVectorTable[i] = (Address) MachHandleDebugTrap;
  388.         machInterruptArgs[i] = (ClientData) 0;
  389. #ifndef sun4c
  390.     }
  391. #endif
  392.     }
  393.  
  394.     /* Temporary: for debugging net module and debugger: */
  395.     mach_NumDisableInterrupts[0] = 1;
  396.  
  397.     /*
  398.      * Copy the boot parameter structure. The original location will get
  399.      * unmapped during vm initialization so we need to get our own copy.
  400.      */
  401.     machMonBootParam = **(romVectorPtr->bootParam);
  402.     offset = (unsigned int) *(romVectorPtr->bootParam) - 
  403.          (unsigned int) &(machMonBootParam);
  404.     for (i = 0; i < 8; i++) {
  405.     if (machMonBootParam.argPtr[i] != (char *) 0 &&
  406.      machMonBootParam.argPtr[i] != (char *) NIL) {
  407.         machMonBootParam.argPtr[i] -= offset;
  408.     }
  409.     }
  410. #ifndef sun4c
  411.     /*
  412.      * Clear out the line input buffer to the prom so we don't get extra
  413.      * characters at the end of shorter reboot strings.
  414.      */
  415.     bzero((char *)(romVectorPtr->lineBuf), *romVectorPtr->lineSize);
  416. #endif
  417.  
  418. #ifdef sun4c
  419.     /*
  420.      * This gets turned on by the profiler init when it is called.
  421.      */
  422.     *Mach_InterruptReg &= ~MACH_ENABLE_LEVEL14_INTR;
  423. #endif
  424.     
  425.  
  426.     return;
  427. }
  428.  
  429.  
  430. /*
  431.  *----------------------------------------------------------------------
  432.  *
  433.  * Mach_InitFirstProc --
  434.  *
  435.  *    Initialize the machine state struct for the very first process.
  436.  *
  437.  * Results:
  438.  *    None.
  439.  *
  440.  * Side effects:
  441.  *    Machine info allocated and stack start set up.
  442.  *
  443.  *----------------------------------------------------------------------
  444.  */
  445. void
  446. Mach_InitFirstProc(procPtr)
  447.     Proc_ControlBlock    *procPtr;
  448. {
  449.     procPtr->machStatePtr = (Mach_State *)Vm_RawAlloc(sizeof(Mach_State));
  450.     bzero((char *)(procPtr->machStatePtr), sizeof (Mach_State));
  451.     procPtr->machStatePtr->kernStackStart = mach_StackBottom;
  452.     procPtr->machStatePtr->trapRegs = (Mach_RegState *) NIL;
  453.     procPtr->machStatePtr->switchRegs = (Mach_RegState *) NIL;
  454.     machCurStatePtr = procPtr->machStatePtr;
  455. }
  456.  
  457.  
  458. /*
  459.  *----------------------------------------------------------------------
  460.  *
  461.  * Mach_SetupNewState --
  462.  *
  463.  *    Initialize the machine state for this process.  This includes 
  464.  *    allocating and initializing a kernel stack.  Assumed that will
  465.  *    be called when starting a process after a fork or restarting a
  466.  *    process after a migration.
  467.  *
  468.  * Results:
  469.  *    PROC_NO_STACKS if couldn't allocate a kernel stack.  SUCCESS otherwise.
  470.  *
  471.  * Side effects:
  472.  *    Machine state in the destination process control block is overwritten.
  473.  *
  474.  *----------------------------------------------------------------------
  475.  */ 
  476. ReturnStatus
  477. Mach_SetupNewState(procPtr, fromStatePtr, startFunc, startPC, user)
  478.     Proc_ControlBlock    *procPtr;    /* Pointer to process control block
  479.                      * to initialize state for. */
  480.     Mach_State        *fromStatePtr;    /* State of parent on fork or from
  481.                      * other machine on migration. */
  482.     void        (*startFunc)();    /* Function to call when process first
  483.                      * starts executing. */
  484.     Address        startPC;    /* Address to pass as argument to 
  485.                      * startFunc.  If NIL then the address
  486.                      * is taken from *fromStatePtr's 
  487.                      * exception stack. */
  488.     Boolean        user;        /* TRUE if is a user process. */
  489. {
  490.     register    Mach_RegState    *stackPtr;
  491.     register    Mach_State    *statePtr;
  492.  
  493.     /*
  494.      * If it's a user process forking, we must make sure all its windows have
  495.      * been saved to the stack so that when the register state and the stack
  496.      * are copied to the new process, it will get the real stuff.
  497.      */
  498.     if (user) {
  499.     Mach_DisableIntr();
  500.     Mach_FlushWindowsToStack();
  501.     Mach_EnableIntr();
  502.     }
  503.     if (procPtr->machStatePtr == (Mach_State *)NIL) {
  504.     procPtr->machStatePtr = (Mach_State *)Vm_RawAlloc(sizeof(Mach_State));
  505.     }
  506.     bzero((char *) procPtr->machStatePtr, sizeof (Mach_State));
  507.     statePtr = procPtr->machStatePtr;
  508.     statePtr->trapRegs = (Mach_RegState *)NIL;
  509.     /* 
  510.      * Allocate a kernel stack for this process.
  511.      */
  512.     statePtr->kernStackStart = (Address) Vm_GetKernelStack(0);
  513.     if (statePtr->kernStackStart == (Address)NIL) {
  514.     return(PROC_NO_STACKS);
  515.     }
  516.  
  517.     /*
  518.      * Pointer to context switch register's save area is also a pointer
  519.      * to the top of the stack, since the regs are saved there.
  520.      * If this is a kernel process, we only need space MACH_SAVED_STATE_FRAME
  521.      * + MACH_FULL_STACK_FRAME, but if it's a user process we need more:
  522.      * (2 * MACH_SAVED_STATE_FRAME).  Both types of processes need the
  523.      * first MACH_SAVED_STATE_FRAME for their context switch regs area.  A
  524.      * kernel process then only needs space under that on its stack for its
  525.      * first routine to store its arguments in its "caller's" stack frame, so
  526.      * this extra space just fakes a caller's stack frame.  But for a user
  527.      * process, we have trap regs.  And these trapRegs get stored under
  528.      * the context switch regs on the kernel stack.
  529.      */
  530.     statePtr->switchRegs = (Mach_RegState *)((statePtr->kernStackStart) +
  531.         MACH_KERN_STACK_SIZE - (2 * MACH_SAVED_STATE_FRAME));
  532.     statePtr->switchRegs = ((unsigned int)(statePtr->switchRegs)) &
  533.         ~0x7;  /* should be okay already */
  534.     /*
  535.      * Initialize the stack so that it looks like it is in the middle of
  536.      * Mach_ContextSwitch.
  537.      */
  538.     stackPtr = statePtr->switchRegs;    /* stack pointer is set from this. */
  539.     /*
  540.      * Fp is set to saved window area for window we'll return to.  The area for
  541.      * the window of Mach_ContextSwitch is a Mach_RegState.  Below this on
  542.      * the stack (at higher address than) is the saved window area of the
  543.      * routine we'll return to from Mach_ContextSwitch.  So the fp must be
  544.      * set to the top of this saved window area.
  545.      */
  546.     *((Address *)(((Address)stackPtr) + MACH_FP_OFFSET)) =
  547.         ((Address)stackPtr) + MACH_SAVED_STATE_FRAME;
  548.     /*
  549.      * We are to return to startFunc from Mach_ContextSwitch, but
  550.      * Mach_ContextSwitch will do a return to retPC + 8, so we subtract
  551.      * 8 from it here to get to the right place.
  552.      */
  553.     *((Address *)(((Address)stackPtr) + MACH_RETPC_OFFSET)) =
  554.         ((Address)startFunc) - 8;
  555.  
  556.     /*
  557.      * Set the psr to restore to have traps enabled and interrupts off.
  558.      */
  559.     stackPtr->curPsr = MACH_HIGH_PRIO_PSR;
  560.     /* 
  561.      * Set up the state of the process.  User processes inherit from their
  562.      * parent or the migrated process.  If the PC is not specified, take it
  563.      * from the parent as well.
  564.      */
  565.     if (user) {
  566.     /*
  567.      * Trap state regs are the same for child process.
  568.      */
  569.     statePtr->trapRegs = (Mach_RegState *)
  570.         (((Address) stackPtr) + MACH_SAVED_STATE_FRAME);
  571.     bcopy((Address)fromStatePtr->trapRegs, (Address)statePtr->trapRegs,
  572.         sizeof (Mach_RegState));
  573.     /*
  574.      * Check to see if any register windows were saved to internal buffer
  575.      * in Mach_FlushWindowsToStack(), above.  If so, copy the buffer state
  576.      * to the new process, so that when it returns from the fork trap, it
  577.      * will copy out the saved windows to its stack.
  578.      */
  579.     if (fromStatePtr->savedMask != 0) {
  580.         procPtr->specialHandling = 1;
  581.         statePtr->savedMask = fromStatePtr->savedMask;
  582.         bcopy((Address) fromStatePtr->savedRegs,
  583.             (Address) statePtr->savedRegs,
  584.             sizeof (fromStatePtr->savedRegs));
  585.         bcopy((Address) fromStatePtr->savedSps,
  586.             (Address) statePtr->savedSps,
  587.             sizeof (fromStatePtr->savedSps));
  588.     }
  589.     }
  590.     if (startPC == (Address)NIL) {
  591.     *((Address *)(((Address)stackPtr) + MACH_ARG0_OFFSET)) =
  592.         (Address) fromStatePtr->trapRegs->pc;
  593.     } else {
  594.     /*
  595.      * The first argument to startFunc is supposed to be startPC.  But that
  596.      * would be in an in register in startFunc's window which is one before
  597.      * Mach_ContextSwitch's window.  But startFunc will do a save operation
  598.      * at the beginning so it will actually be executing in Mach_ContextS's
  599.      * window, so arg0 to startFunc must actually be arg0 that is restored
  600.      * at the end of Mach_ContextSwitch, so we have to put it in the in
  601.      * register area of Mach_RegState area on the stack.  Weird.
  602.      */
  603.     *((Address *)(((Address)stackPtr) + MACH_ARG0_OFFSET)) = startPC;
  604.     }
  605.     return(SUCCESS);
  606. }
  607.  
  608. /*
  609.  *----------------------------------------------------------------------
  610.  *
  611.  * Mach_SetReturnVal --
  612.  *
  613.  *    Set the return value for a process from a system call.  Intended to
  614.  *    be called by the routine that starts a user process after a fork.
  615.  *    Interrupts must be off here!
  616.  *
  617.  * Results:
  618.  *    None.
  619.  *
  620.  * Side effects:
  621.  *    Register D0 is set in the user registers.
  622.  *
  623.  *----------------------------------------------------------------------
  624.  */ 
  625. void
  626. Mach_SetReturnVal(procPtr, retVal, retVal2)
  627.     Proc_ControlBlock    *procPtr;    /* Process to set return value for. */
  628.     int            retVal;        /* Value for process to return. */
  629.     int            retVal2;    /* 2nd Value for process to return. */
  630. {
  631.     if (procPtr->machStatePtr->trapRegs == (Mach_RegState *) NIL ||
  632.         procPtr->machStatePtr->trapRegs == (Mach_RegState *) 0) {
  633.     return;
  634.     }
  635.     procPtr->machStatePtr->trapRegs->ins[0] = retVal;
  636.     procPtr->machStatePtr->trapRegs->ins[1] = retVal2;
  637.     return;
  638. }
  639.  
  640.  
  641. /*
  642.  *----------------------------------------------------------------------
  643.  *
  644.  * Mach_StartUserProc --
  645.  *
  646.  *    Start a user process executing for the first time.
  647.  *    Interrupts must be off here!
  648.  *
  649.  * Results:
  650.  *    None.
  651.  *
  652.  * Side effects:
  653.  *    Stack pointer and the program counter set for the process and
  654.  *    the current process's image is replaced.
  655.  *
  656.  *----------------------------------------------------------------------
  657.  */
  658. void
  659. Mach_StartUserProc(procPtr, entryPoint)
  660.     Proc_ControlBlock    *procPtr;    /* Process control block for process
  661.                      * to start. */
  662.     Address        entryPoint;    /* Where process is to start
  663.                      * executing. */
  664. {
  665.     register    Mach_State    *statePtr;
  666.  
  667.     statePtr = procPtr->machStatePtr;
  668.     /*
  669.      * MachRunUserProc will put the values from our trap regs into the actual
  670.      * registers so that we'll be in shape to rett back to user mode.
  671.      */
  672.     Mach_DisableIntr();
  673.  
  674.     /*
  675.      * Return from trap pc.
  676.      */
  677.     statePtr->trapRegs->pc = (unsigned int) entryPoint;
  678.     statePtr->trapRegs->nextPc = (unsigned int) (entryPoint + 4);
  679.  
  680.     MachRunUserProc();
  681.     /* THIS DOES NOT RETURN */
  682. }
  683.  
  684.  
  685. /*
  686.  *----------------------------------------------------------------------
  687.  *
  688.  * Mach_ExecUserProc --
  689.  *
  690.  *    Replace the calling user process's image with a new one.
  691.  *
  692.  * Results:
  693.  *    None.
  694.  *
  695.  * Side effects:
  696.  *    Stack pointer set for the process.
  697.  *
  698.  *----------------------------------------------------------------------
  699.  */
  700. void
  701. Mach_ExecUserProc(procPtr, userStackPtr, entryPoint)
  702.     Proc_ControlBlock    *procPtr;        /* Process control block for
  703.                          * process to exec. */
  704.     Address        userStackPtr;        /* Stack pointer for when the
  705.                          * user process resumes 
  706.                          * execution. */
  707.     Address        entryPoint;        /* Where the user process is
  708.                          * to resume execution. */
  709. {
  710.     Mach_RegState    tmpTrapState;
  711.  
  712.     /*
  713.      * Ugh.  They set this to a different register set in the sun3 and
  714.      * then set this reg differently in Mach_StartUserProc.  What should I
  715.      * be doing?
  716.      */
  717.     /*
  718.      * EEK -- Make sure there's enough space here for thing to have
  719.      * stored its 6 input reg args in a caller's stack frame.
  720.      */
  721.      /*
  722.       * We do not call DISABLE_INTR here because there's an implicit enable
  723.       * of interrupts in MachRunUserProc().
  724.       */
  725.     Mach_DisableIntr();
  726.     machCurStatePtr = procPtr->machStatePtr;
  727.     /*
  728.      * Since we're not returning, we can just use this space on our kernel
  729.      * stack as trapRegs.  This is safe, since we only fill in the fp, tbr,
  730.      * pc, and nextPc fields (in Mach_StartUserProc()) and these just touch
  731.      * the saved-window section of our stack and won't mess up any of our
  732.      * arguments.
  733.      */
  734.     procPtr->machStatePtr->trapRegs = &tmpTrapState;
  735.     /*
  736.      * The user stack pointer gets MACH_FULL_STACK_FRAME subtracted from it
  737.      * so that the user stack has space for its first routine to store its
  738.      * arguments in its caller's stack frame.  (So we create a fake caller's
  739.      * stack frame this way.)
  740.      */
  741.     procPtr->machStatePtr->trapRegs->ins[MACH_FP_REG] = (unsigned int)
  742.         (userStackPtr - MACH_FULL_STACK_FRAME);
  743.     procPtr->machStatePtr->trapRegs->curPsr = MACH_FIRST_USER_PSR;
  744.     procPtr->machStatePtr->trapRegs->pc = (unsigned int) entryPoint;
  745.     procPtr->machStatePtr->trapRegs->tbr = (unsigned int) machTBRAddr;
  746.     /*
  747.      * Initialized the floating point state.
  748.      */
  749.     procPtr->machStatePtr->fpuStatus = 0;
  750.     /*
  751.      * Return value is cleared for exec'ing user process.  This shouldn't
  752.      * matter since a good exec won't return.
  753.      */
  754.     procPtr->machStatePtr->trapRegs->ins[0] = 0;
  755.     Mach_StartUserProc(procPtr, entryPoint);
  756.     /* THIS DOES NOT RETURN */
  757. }
  758.  
  759. /*
  760.  *----------------------------------------------------------------------
  761.  *
  762.  * Mach_FreeState --
  763.  *
  764.  *    Free up the machine state for the given process control block.
  765.  *
  766.  * Results:
  767.  *    None.
  768.  *
  769.  * Side effects:
  770.  *    Free up the kernel stack.
  771.  *
  772.  *----------------------------------------------------------------------
  773.  */
  774. void
  775. Mach_FreeState(procPtr)
  776.     Proc_ControlBlock    *procPtr;    /* Process control block to free
  777.                      * machine state for. */
  778. {
  779.  
  780.     if (procPtr->machStatePtr->kernStackStart != (Address)NIL) {
  781.     Vm_FreeKernelStack(procPtr->machStatePtr->kernStackStart);
  782.     procPtr->machStatePtr->kernStackStart = (Address)NIL;
  783.     }
  784. }
  785.  
  786.  
  787. /*
  788.  *----------------------------------------------------------------------
  789.  *
  790.  * Mach_GetDebugState --
  791.  *
  792.  *    Extract the appropriate fields from the machine state struct
  793.  *    and store them into the debug struct.
  794.  *
  795.  * Results:
  796.  *    None.
  797.  *
  798.  * Side effects:
  799.  *    Debug struct filled in from machine state struct.
  800.  *
  801.  *----------------------------------------------------------------------
  802.  */ 
  803. void
  804. Mach_GetDebugState(procPtr, debugStatePtr)
  805.     Proc_ControlBlock    *procPtr;
  806.     Proc_DebugState    *debugStatePtr;
  807. {
  808.     register    Mach_State    *machStatePtr;
  809.  
  810.     machStatePtr = procPtr->machStatePtr;
  811.     bcopy((Address)machStatePtr->trapRegs,
  812.           (Address)(&debugStatePtr->regState), sizeof(Mach_DebugState));
  813.     return;
  814. }
  815.  
  816.  
  817. /*
  818.  *----------------------------------------------------------------------
  819.  *
  820.  * Mach_SetDebugState --
  821.  *
  822.  *    Extract the appropriate fields from the debug struct
  823.  *    and store them into the machine state struct.
  824.  *
  825.  * Results:
  826.  *    None.
  827.  *
  828.  * Side effects:
  829.  *    Machine state struct filled in from the debug state struct.
  830.  *
  831.  *----------------------------------------------------------------------
  832.  */ 
  833. void
  834. Mach_SetDebugState(procPtr, debugStatePtr)
  835.     Proc_ControlBlock    *procPtr;
  836.     Proc_DebugState    *debugStatePtr;
  837. {
  838.     register    Mach_State    *machStatePtr;
  839.  
  840. /* y, pc's g1-g7 all in's*/
  841.     machStatePtr = procPtr->machStatePtr;
  842.     machStatePtr->trapRegs->pc = debugStatePtr->regState.pc;
  843.     machStatePtr->trapRegs->nextPc = debugStatePtr->regState.nextPc;
  844.     machStatePtr->trapRegs->y = debugStatePtr->regState.y;
  845.     bcopy((Address)debugStatePtr->regState.ins,
  846.         (Address)machStatePtr->trapRegs->ins, MACH_NUM_INS * sizeof (int));
  847.     bcopy((Address)debugStatePtr->regState.globals,
  848.         (Address)machStatePtr->trapRegs->globals,
  849.         MACH_NUM_GLOBALS * sizeof (int));
  850.     return;
  851. }
  852.  
  853.  
  854. /*
  855.  *----------------------------------------------------------------------
  856.  *
  857.  * Mach_InitSyscall --
  858.  *
  859.  *    During initialization, this procedure is called once for each
  860.  *    kernel call, in order to set up information used to dispatch
  861.  *    the kernel call.  This procedure must be called once for each
  862.  *    kernel call, in order starting at 0.
  863.  *
  864.  * Results:
  865.  *    None.
  866.  *
  867.  * Side effects:
  868.  *    Initializes the dispatch tables for the kernel call.
  869.  *
  870.  *----------------------------------------------------------------------
  871.  */
  872. void
  873. Mach_InitSyscall(callNum, numArgs, normalHandler, migratedHandler)
  874.     int callNum;            /* Number of the system call. */
  875.     int numArgs;            /* Number of one-word arguments passed
  876.                      * into call on stack. */
  877.     ReturnStatus (*normalHandler)();    /* Procedure to process kernel call
  878.                      * when process isn't migrated. */
  879.     ReturnStatus (*migratedHandler)();    /* Procedure to process kernel call
  880.                      * for migrated processes. */
  881. {
  882.     machMaxSysCall++;
  883.     if (machMaxSysCall != callNum) {
  884.     printf("Warning: out-of-order kernel call initialization, call %d\n",
  885.            callNum);
  886.     }
  887.     if (machMaxSysCall >= SYS_NUM_SYSCALLS) {
  888.     printf("Warning: too many kernel calls.\n");
  889.     machMaxSysCall--;
  890.     return;
  891.     }
  892.     if (numArgs > SYS_MAX_ARGS) {
  893.     printf("Warning: too many arguments to kernel call %d\n", callNum);
  894.     numArgs = SYS_MAX_ARGS;
  895.     }
  896.     /*
  897.      * Offset of beginning of args on stack - offset from frame pointer.
  898.      * Figure out offset  from fp of params past the sixth.
  899.      * It copies from last arg to first
  900.      * arg in that order, so we start offset at bottom of last arg.
  901.      */
  902.     /*
  903.      * TURN THESE INTO PROPER CONSTANTS!
  904.      */
  905.     /*
  906.      * We copy going towards higher addresses, rather than lower, as the sun3
  907.      * does it.  So our offset is at top of extra parameters to copy, and not
  908.      * below them (stack-wise speaking, not address-wise speaking).
  909.      */
  910.     machArgOffsets[machMaxSysCall] = MACH_SAVED_WINDOW_SIZE +
  911.         MACH_ACTUAL_HIDDEN_AND_INPUT_STORAGE;
  912.     
  913.     /*
  914.      * Where to jump to in fetching routine to copy the right amount from
  915.      * the stack.  The fewer args we have, the farther we jump...  Figure out
  916.      * how many are in registers, then do rest from stack.  There's instructions
  917.      * to copy 10 words worth, for now, since 6 words worth of arguments are
  918.      * in the input registers.  If this number changes, change machTrap.s
  919.      * and the jump offset below!
  920.      */
  921.     if (numArgs <= 6) {
  922.     machArgDispatch[machMaxSysCall] =  (Address) MachFetchArgsEnd;
  923.     } else {
  924.     machArgDispatch[machMaxSysCall] = (10 - (numArgs - 6))*16 +
  925.         ((Address)MachFetchArgs);
  926.     }
  927.     mach_NormalHandlers[machMaxSysCall] = normalHandler;
  928.     mach_MigratedHandlers[machMaxSysCall] = migratedHandler;
  929. }
  930.  
  931.  
  932. /*
  933.  * ----------------------------------------------------------------------------
  934.  *
  935.  * Mach_SetHandler --
  936.  *
  937.  *    This is used both for autovectored devices and for regular interrupt
  938.  *    routines for device interrupt levels.  For autovectored devices,
  939.  *    the routine MachVectoredInterrupt will already have been installed
  940.  *    for the auto-vectored interrupt levels.  Then this routine should be
  941.  *    be called with the interrrupt vector for the device and its
  942.  *    real interrupt handler.  For non-autovectored interrupt handlers, the
  943.  *    handler should just be installed with a vector that is the
  944.  *    device's interrupt level.
  945.  *
  946.  * Results:
  947.  *     None.
  948.  *
  949.  * Side effects:
  950.  *     The exception vector table is modified.
  951.  *
  952.  * ----------------------------------------------------------------------------
  953.  */
  954. void
  955. Mach_SetHandler(vectorNumber, handler, clientData)
  956.     int vectorNumber;        /* Vector number that the device generates */
  957.     int (*handler)();        /* Interrupt handling procedure */
  958.     ClientData    clientData;    /* ClientData for interrupt callback routine. */
  959. {
  960.  
  961.     if (vectorNumber < 0 || vectorNumber > 255) {
  962.     panic("Warning: Bad vector number %d\n", vectorNumber);
  963.     } else {
  964.     machVectorTable[vectorNumber] = (Address) handler;
  965.     machInterruptArgs[vectorNumber] = (ClientData) clientData;
  966.     }
  967. }
  968.  
  969.  
  970. /*
  971.  * ----------------------------------------------------------------------------
  972.  *
  973.  * Routines to set up and return from signal handlers.
  974.  *
  975.  * In order to call a handler four things must be done:
  976.  *
  977.  *    1) The current state of the process must be saved so that when
  978.  *       the handler returns a normal return to user space can occur.
  979.  *    2) The user stack must be set up so that the signal number and the
  980.  *       the signal code are passed to the handler.
  981.  *    3) Things must be set up so that when the handler returns it returns
  982.  *       back into the kernel so that state can be cleaned up.
  983.  *    4) The trap stack that was created when the kernel was entered and is
  984.  *       used to return a process to user space must be modified so that
  985.  *       the signal handler is called instead of executing the
  986.  *       normal return.
  987.  *
  988.  * The last one is done by simply changing the program counter where the
  989.  * user process will execute on return to be the address of the signal
  990.  * handler and the user stack pointer to point to the proper place on
  991.  * the user stack.  The first three of these are accomplished by 
  992.  * setting up the user stack properly.  The top entry on the stack is the
  993.  * return address where the handler will start executing upon return.  But 
  994.  * this is just the address of a trap instruction that is stored on the stack
  995.  * below.  Thus when a handler returns it will execute a trap instruction 
  996.  * and drop back into the kernel. 
  997.  */
  998.  
  999.  
  1000. /*
  1001.  * ----------------------------------------------------------------------------
  1002.  *
  1003.  * MachCallSigReturn --
  1004.  *
  1005.  *      Process a return from a signal handler.  Call the Sig_Return
  1006.  *    routine with appropriate args.
  1007.  *    
  1008.  * Results:
  1009.  *      None.
  1010.  *
  1011.  * Side effects:
  1012.  *    Whatever Sig_Return does.
  1013.  *
  1014.  * ----------------------------------------------------------------------------
  1015.  */
  1016. void
  1017. MachCallSigReturn()
  1018. {
  1019.     Proc_ControlBlock    *procPtr;
  1020.     Mach_State        *statePtr;
  1021.     Sig_Stack        *sigStackPtr;
  1022.  
  1023.     procPtr = Proc_GetCurrentProc();
  1024.     statePtr = procPtr->machStatePtr;
  1025.  
  1026.     sigStackPtr = &(statePtr->sigStack);
  1027.     sigStackPtr->contextPtr = &(statePtr->sigContext);
  1028.  
  1029.     /*
  1030.      * Take the proper action on return from a signal.
  1031.      */
  1032.     Sig_Return(procPtr, sigStackPtr);
  1033. }
  1034.  
  1035.  
  1036. /*
  1037.  * ----------------------------------------------------------------------------
  1038.  *
  1039.  * Mach_ProcessorState --
  1040.  *
  1041.  *    Determines what state the processor is in.
  1042.  *
  1043.  * Results:
  1044.  *    MACH_USER    if was at user level
  1045.  *    MACH_KERNEL    if was at kernel level
  1046.  *
  1047.  * Side effects:
  1048.  *    None.
  1049.  *
  1050.  * ----------------------------------------------------------------------------
  1051.  */
  1052. /*ARGSUSED*/
  1053. Mach_ProcessorStates 
  1054. Mach_ProcessorState(processor)
  1055.     int processor;    /* processor number for which info is requested */
  1056. {
  1057.     if (mach_KernelMode) {
  1058.     return(MACH_KERNEL);
  1059.     } else {
  1060.     return(MACH_USER);
  1061.     }
  1062. }
  1063.  
  1064.  
  1065. /*
  1066.  * ----------------------------------------------------------------------------
  1067.  *
  1068.  * Mach_GetMachineArch --
  1069.  *
  1070.  *    Return the machine architecture (SYS_SUN2 or SYS_SUN3).
  1071.  *
  1072.  * Results:
  1073.  *    The machine architecture.
  1074.  *
  1075.  * Side effects:
  1076.  *    None.
  1077.  *
  1078.  * ----------------------------------------------------------------------------
  1079.  */
  1080. int
  1081. Mach_GetMachineArch()
  1082. {
  1083. #       ifdef sun2
  1084.     return SYS_SUN2;
  1085. #       endif sun2
  1086.  
  1087. #       ifdef sun3
  1088.     return SYS_SUN3;
  1089. #       endif sun3
  1090.  
  1091. #    ifdef sun4
  1092.     return SYS_SUN4;
  1093. #    endif sun4
  1094. }
  1095.  
  1096. /*
  1097.  * ----------------------------------------------------------------------------
  1098.  *
  1099.  *  Mach_CheckSpecialHandling--
  1100.  *
  1101.  *    Forces a processor to check the special handling flag of a process.
  1102.  *    This should only be called on a multiprocessor.
  1103.  *
  1104.  * Results:
  1105.  *    None.
  1106.  *
  1107.  * Side effects:
  1108.  *    None.
  1109.  *
  1110.  * ----------------------------------------------------------------------------
  1111.  */
  1112. void
  1113. Mach_CheckSpecialHandling(pnum)
  1114.     int        pnum;        /* Processor number. */
  1115. {
  1116.     panic("Mach_CheckSpecialHandling called for processor %d\n",pnum);
  1117. }
  1118.  
  1119.  
  1120. /*
  1121.  *----------------------------------------------------------------------
  1122.  *
  1123.  * Mach_GetNumProcessors() --
  1124.  *
  1125.  *    Return the number of processors in the system.  NOTE: This should
  1126.  *    really be in a machine-independent area of the mach module.  Note
  1127.  *    further: if this is used only as a system call, it should return
  1128.  *    a ReturnStatus!
  1129.  *
  1130.  * Results:
  1131.  *    The number of processors is returned.  
  1132.  *
  1133.  * Side effects:
  1134.  *    None
  1135.  *
  1136.  *----------------------------------------------------------------------
  1137.  */
  1138.  
  1139. int
  1140. Mach_GetNumProcessors()
  1141. {
  1142.     return (mach_NumProcessors);
  1143. }
  1144.  
  1145.  
  1146.  
  1147. /*
  1148.  *----------------------------------------------------------------------
  1149.  *
  1150.  * MachPageFault() -
  1151.  *
  1152.  *    Handle a page fault.
  1153.  *
  1154.  * Results:
  1155.  *    None
  1156.  *
  1157.  * Side effects:
  1158.  *    A page causing a memory access error is made valid.  If it's an
  1159.  *    illegal page fault in the kernel, we will call panic.
  1160.  *
  1161.  *----------------------------------------------------------------------
  1162.  */
  1163. void
  1164. MachPageFault(busErrorReg, addrErrorReg, trapPsr, pcValue)
  1165.     unsigned    int    busErrorReg;
  1166.     Address        addrErrorReg;
  1167.     unsigned    int    trapPsr;
  1168.     Address        pcValue;
  1169. {
  1170.     Proc_ControlBlock    *procPtr;
  1171.     Boolean        protError;
  1172.     Boolean        copyInProgress = FALSE;
  1173.     ReturnStatus    status;
  1174.     extern        int    VmMachQuickNDirtyCopy();
  1175.     extern        int    VmMachEndQuickCopy();
  1176.  
  1177.     /*
  1178.      * Are we in quick cross-context copy routine?  If so, we can't page fault
  1179.      * in it.
  1180.      */
  1181.     if ((pcValue >= (Address) VmMachQuickNDirtyCopy) &&
  1182.         (pcValue < (Address) VmMachEndQuickCopy)) {
  1183.     /*
  1184.      * This doesn't return to here.  It erases the fact that the
  1185.      * page fault happened and makes the copy routine that
  1186.      * got the page fault return FAILURE to its caller.  We must turn off
  1187.      * interrupts before calling MachHandleBadQuickCopy().
  1188.      */
  1189.     Mach_DisableIntr();
  1190.     MachHandleBadQuickCopy();
  1191.     Mach_EnableIntr();
  1192.     }
  1193.     /*
  1194.      * Are we poking at or peeking into memory-mapped devices?
  1195.      * We must check this before looking for the current process, since this
  1196.      * can happen during boot-time before we have set up processes.
  1197.      */
  1198.     if ((pcValue >= (Address) &MachProbeStart)  &&
  1199.         (pcValue < (Address) &MachProbeEnd)) {
  1200.     /*
  1201.      * This doesn't return to here.  It erases the fact that the
  1202.      * page fault happened and makes the probe routine that
  1203.      * got the page fault return FAILURE to its caller.  We must turn off
  1204.      * interrupts before calling MachHandleBadProbe().
  1205.      */
  1206.     Mach_DisableIntr();
  1207.     MachHandleBadProbe();
  1208.     Mach_EnableIntr();
  1209.     }
  1210. #ifdef sun4
  1211.     /*
  1212.      * On the sun4/200 with the Jaguar HBA we get VME timeout errors from 
  1213.      * the board. This code retries the error up to 10 times before droping
  1214.      * into the code below which panics. 
  1215.      */
  1216.     {
  1217.     static timeoutRetryCount = 0;
  1218.     extern void MachVectoredInterruptLoad();
  1219.  
  1220.     if ((trapPsr & MACH_PS_BIT) && (busErrorReg == MACH_TIMEOUT_ERROR)) {
  1221.         /*
  1222.          * If the error occurred on a the load of the interrupt
  1223.          * vector make the routine return.
  1224.          */
  1225.         if (pcValue == (Address) MachVectoredInterruptLoad) {
  1226.         /*
  1227.          * This doesn't return to here.  It erases the fact that the
  1228.          * page fault happened and makes the MachVectoredInterrupt
  1229.          * routine that got the page fault return FAILURE 
  1230.          * to its caller.  
  1231.          */
  1232.         Mach_MonPrintf(
  1233. "MachPageFault: Bus timeout error on VME interrupt vector load pc:0x%x, addr:0x%x\n",
  1234.              pcValue, addrErrorReg);
  1235.         MachHandleBadQuickCopy();
  1236.         }
  1237.         Mach_MonPrintf(
  1238.  "MachPageFault: Bus timeout error retry %d at pc:0x%x, addr:0x%x\n",
  1239.             timeoutRetryCount, pcValue, addrErrorReg);
  1240.         if (timeoutRetryCount < 10) {
  1241.         timeoutRetryCount++;
  1242.         return;
  1243.         }
  1244.     }
  1245.     timeoutRetryCount = 0;
  1246.     }
  1247. #endif /* sun4 */
  1248.  
  1249.     procPtr = Proc_GetActualProc();
  1250.     if (procPtr == (Proc_ControlBlock *) NIL) {
  1251.     panic(
  1252.     "MachPageFault: Current process is NIL!!  Trap pc is 0x%x, addr 0x%x\n",
  1253.         (unsigned) pcValue, addrErrorReg);
  1254.     }
  1255.     /* process kernel page fault */
  1256.     if (trapPsr & MACH_PS_BIT) {        /* kernel mode before trap */
  1257.     if (!(procPtr->genFlags & PROC_USER)) {
  1258.         /*
  1259.          * This fault happened inside the kernel and it wasn't on behalf
  1260.          * of a user process.  This is an error.
  1261.          */
  1262.         panic(
  1263. "MachPageFault: page fault in kernel process! pc:0x%x, addr:0x%x, Error:0x%x\n",
  1264.             pcValue, addrErrorReg, busErrorReg);
  1265.     }
  1266.     /*
  1267.      * A page fault on a user process while executing in
  1268.      * the kernel.  This can happen when information is
  1269.      * being copied back and forth between kernel and user state
  1270.      * (indicated by particular values of the program counter).
  1271.      */
  1272.     if ((pcValue >= (Address) Vm_CopyIn) &&
  1273.         (pcValue < (Address) VmMachCopyEnd)) {
  1274.         copyInProgress = TRUE;
  1275.     } else if ((pcValue >= (Address) MachFetchArgs) &&
  1276.         (pcValue <= (Address) MachFetchArgsEnd)) {
  1277.         copyInProgress = TRUE;
  1278.     } else if (procPtr->vmPtr->numMakeAcc == 0) {
  1279.         /*
  1280.          * ERROR: pc faulted in a bad place!
  1281.          */
  1282.         panic(
  1283.         "MachPageFault: kernel page fault at illegal pc: 0x%x, addr 0x%x\n",
  1284.             pcValue, addrErrorReg);
  1285.     }
  1286.     protError = (busErrorReg & MACH_PROT_ERROR);
  1287.     /*
  1288.      * Try to fault in the page.
  1289.      */
  1290.     status = Vm_PageIn(addrErrorReg, protError);
  1291.     if (status != SUCCESS) {
  1292.         if (copyInProgress) {
  1293.         /*
  1294.          * This doesn't return to here.  It erases the fact that the
  1295.          * page fault happened and makes the copy routine that
  1296.          * got the page fault return SYS_ARG_NO_ACCESS to its caller.
  1297.          * We must turn off interrupts before calling
  1298.          * MachHandleBadArgs().
  1299.          */
  1300.         Mach_DisableIntr();
  1301.         MachHandleBadArgs();
  1302.         Mach_EnableIntr();
  1303.         } else {
  1304.         /* kernel error */
  1305.         panic(
  1306.         "MachPageFault: couldn't page in kernel page at 0x%x, pc 0x%x\n",
  1307.             addrErrorReg, pcValue);
  1308.         }
  1309.     }
  1310.     return;
  1311.     }
  1312.     /* user page fault */
  1313.     protError = busErrorReg & MACH_PROT_ERROR;
  1314.     if (Vm_PageIn(addrErrorReg, protError) != SUCCESS) {
  1315.     printf(
  1316.     "MachPageFault: Bus error in user proc %x, PC = %x, addr = %x BR Reg %x\n",
  1317. #ifdef sun4c
  1318.         procPtr->processID, pcValue, addrErrorReg, busErrorReg);
  1319. #else
  1320.         procPtr->processID, pcValue, addrErrorReg, (short) busErrorReg);
  1321. #endif
  1322.     /* Kill user process */
  1323.     Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, procPtr->processID, FALSE,
  1324.            (Address)addrErrorReg);
  1325.     return;
  1326.     }
  1327.     return;
  1328. }
  1329.  
  1330.  
  1331. /*
  1332.  *----------------------------------------------------------------------
  1333.  *
  1334.  * MachUserAction() -
  1335.  *
  1336.  *    Check what sort of user-process action is needed.  We already know
  1337.  *    that some sort of action is needed, since the specialHandling flag
  1338.  *    should be checked before calling this routine.  The possible actions
  1339.  *    are to take a context switch, to push saved user windows from the mach
  1340.  *    state structure out to the user stack, or to set things up to handle
  1341.  *    pending signals.  We assume traps are enabled before this routine is
  1342.  *    called.
  1343.  *
  1344.  * Results:
  1345.  *    The return value 0 indicates we have no pending signal.
  1346.  *    The return value 1 indicates we have a pending Sprite signal.
  1347.  *    The return value 2 indicates we have a pending Unix signal.
  1348.  *
  1349.  * Side effects:
  1350.  *    The mach state structure may change, especially the mask that indicates
  1351.  *    which windows were saved into the internal buffer.
  1352.  *
  1353.  *----------------------------------------------------------------------
  1354.  */
  1355. int
  1356. MachUserAction()
  1357. {
  1358.     Proc_ControlBlock    *procPtr;
  1359.     Mach_State        *machStatePtr;
  1360.     Sig_Stack        *sigStackPtr;
  1361.     Address        pc;
  1362.     int            unixSignal;
  1363.     int            restarted=0;
  1364.  
  1365.     procPtr = Proc_GetCurrentProc();
  1366.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1367.             procPtr->unixProgress != PROC_PROGRESS_UNIX && debugProcStubs) {
  1368.         printf("UnixProgress = %d entering MachUserReturn\n",
  1369.         procPtr->unixProgress);
  1370.     }
  1371.  
  1372. HandleItAgain:
  1373.     if (procPtr->Prof_Scale != 0 && procPtr->Prof_PC != 0) {
  1374.     Prof_RecordPC(procPtr);
  1375.     }
  1376.     procPtr->specialHandling = 0;
  1377.     /*
  1378.      * Take a context switch if one is pending for this process.
  1379.      * If other stuff, such as flushing the windows to the stack needs to
  1380.      * be done, it will happen when the process is switched back in again.
  1381.      * We came from MachReturnFromTrap, where interrupts were off, so we
  1382.      * must turn them on.
  1383.      */
  1384.     Mach_EnableIntr();
  1385.     if (procPtr->schedFlags & SCHED_CONTEXT_SWITCH_PENDING) {
  1386.     Sched_LockAndSwitch();
  1387.     }
  1388.  
  1389.     machStatePtr = procPtr->machStatePtr;
  1390.  
  1391.     /*
  1392.      * Save the windows that were stored in internal buffers to the user stack.
  1393.      * The windows were saved to internal buffers due to the user stack not
  1394.      * being resident.  The overflow handler can't take page faults, but
  1395.      * we can.
  1396.      */
  1397.     if (machStatePtr->savedMask != 0) {
  1398.     int    i;
  1399.  
  1400.     for (i = 0; i < MACH_NUM_WINDOWS; i++) {
  1401.         if ((1 << i) & machStatePtr->savedMask) {
  1402.         /*
  1403.          * Clear the mask for this window.  We must turn off interrupts
  1404.          * to do this, since changing the savedMask must be an
  1405.          * atomic operation.  If it weren't, and an interrupt came
  1406.          * in that caused us to save some other window to the stack
  1407.          * after we have read the savedMask, we would overwrite the
  1408.          * fact when storing the saved Mask...
  1409.          */
  1410.         Mach_DisableIntr();
  1411.         machStatePtr->savedMask &= ~(1 << i);
  1412.         Mach_EnableIntr();
  1413.         /*
  1414.          * Push the window to the stack.
  1415.          */ 
  1416.         if (Vm_CopyOut(MACH_SAVED_WINDOW_SIZE,
  1417.             (Address)(machStatePtr->savedRegs[i]),
  1418.             (Address)(machStatePtr->savedSps[i])) != SUCCESS) {
  1419.             printf("MachUserAction: pid 0x%x being killed: %s 0x%x.\n",
  1420.                 procPtr->processID, "bad stack pointer?",
  1421.                 machStatePtr->savedSps[i]);
  1422.             Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1423.         }
  1424.         }
  1425.     }
  1426.     }
  1427.     /*
  1428.      * We must check again here to see if the specialHandling flag has been
  1429.      * set again.  We've been taking interrupts this whole time, and the
  1430.      * Vm code above may have called deeply, so we may have saved further
  1431.      * user windows to internal buffers.  If we have, go back up to the
  1432.      * beginning of the routine, and do this all again.
  1433.      */
  1434.  
  1435.     /*
  1436.      * For now, we also flush all the windows to make sure the signal-handling
  1437.      * stuff below won't cause us to save windows to internal buffers.  This
  1438.      * is a slow thing to do, but it is currenlty unclear what to do if
  1439.      * the signal handler causes a window to get saved to an internal buffer.
  1440.      * It will have to call some sort of MachUserAction-type routine itself
  1441.      * in that case.
  1442.      */
  1443.     Mach_DisableIntr();
  1444.     Mach_FlushWindowsToStack();
  1445.     if (procPtr->specialHandling != 0) {
  1446.     goto HandleItAgain;
  1447.     }
  1448.     Mach_EnableIntr();
  1449.     /*
  1450.      * Check for floating point problems.
  1451.      */
  1452.     if (machStatePtr->fpuStatus & MACH_FPU_EXCEPTION_PENDING) {
  1453.     HandleFPUException(procPtr, machStatePtr);
  1454.     }
  1455.     /*
  1456.      * Now check for signal stuff. We must check again for floating
  1457.      * point exception because the Sig_Handle might do a context switch
  1458.      * during which the excpetion would get posted. 
  1459.      * 
  1460.      * Note: This is really wrong.  We should check for and process 
  1461.      * any floating point exceptions before  handling a signal. 
  1462.      * The problem here is by the time Sig_Handle returns we are
  1463.      * already committed to doing this signal.
  1464.      */
  1465.     sigStackPtr = &(machStatePtr->sigStack);
  1466.     sigStackPtr->contextPtr = &(machStatePtr->sigContext);
  1467.     if (procPtr->unixProgress == PROC_PROGRESS_RESTART ||
  1468.         procPtr->unixProgress > 0) {
  1469.     /*
  1470.      * If we received a normal signal, we want to restart
  1471.      * the system call when we leave.
  1472.      * If we received a migrate signal, we will get here on
  1473.      * the new machine.
  1474.      * We must also ensure that the argument registers are the
  1475.      * same as when we came in.
  1476.      */
  1477.     restarted = 1;
  1478.     if (debugProcStubs) {
  1479.         printf("Restarting system call with progress %d\n",
  1480.             procPtr->unixProgress);
  1481.     }
  1482.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1483.  
  1484.     }
  1485.     if (Sig_Handle(procPtr, sigStackPtr, &pc)) {
  1486.     machStatePtr->sigContext.machContext.pcValue = pc;
  1487.     machStatePtr->sigContext.machContext.trapInst = MACH_SIG_TRAP_INSTR;
  1488.     /* leave interrupts disabled */
  1489.     if (machStatePtr->fpuStatus & MACH_FPU_EXCEPTION_PENDING) {
  1490.         HandleFPUException(procPtr, machStatePtr);
  1491.     }
  1492.     Mach_DisableIntr();
  1493.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX) {
  1494.         /*
  1495.          * We have to build a proper Unix signal stack.
  1496.          */
  1497.         int n[16];
  1498.         struct sigcontext    unixContext;
  1499.         procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1500.         if (Compat_SpriteSignalToUnix(sigStackPtr->sigNum,
  1501.             &unixSignal) != SUCCESS) {
  1502.         printf("Signal %d invalid in SetupSigHandler\n",
  1503.             sigStackPtr->sigNum);
  1504.         return 0;
  1505.         }
  1506.  
  1507.         if (restarted) {
  1508.         if (debugProcStubs) {
  1509.             printf("Moving PC to restart system call (doing signal\n");
  1510.         }
  1511.         machStatePtr->trapRegs->nextPc = machStatePtr->trapRegs->pc;
  1512.         machStatePtr->trapRegs->pc = machStatePtr->trapRegs->nextPc-4;
  1513.         /*
  1514.          * We need to restore %o0 which got clobbered by
  1515.          * the system call.
  1516.          */
  1517.         machStatePtr->trapRegs->ins[0] = machStatePtr->savedArgI0;
  1518.         }
  1519.  
  1520.         if (debugProcStubs) {
  1521.         printf("Unix signal %d(%d) to %x\n", sigStackPtr->sigNum,
  1522.             unixSignal, procPtr->processID);
  1523.         }
  1524.         sigStackPtr->sigNum = unixSignal;
  1525.         unixContext.sc_onstack = 0;
  1526.         unixContext.sc_mask = machStatePtr->sigContext.oldHoldMask;
  1527.         unixContext.sc_sp = machStatePtr->trapRegs->ins[6];
  1528.         /*
  1529.          * pc and npc are where to continue the interrupted routine.
  1530.          */
  1531.         if (debugProcStubs) {
  1532.         printf("PSR = %x\n", machStatePtr->trapRegs->curPsr);
  1533.         }
  1534.         unixContext.sc_pc = machStatePtr->trapRegs->pc;
  1535.         unixContext.sc_npc = machStatePtr->trapRegs->nextPc;
  1536.         if (debugProcStubs) {
  1537.         printf("trapRegs->pc=%x, trapRegs->npc=%x, context.pcValue=%x\n",
  1538.             machStatePtr->trapRegs->pc, machStatePtr->trapRegs->nextPc,
  1539.             machStatePtr->sigContext.machContext.pcValue);
  1540.         }
  1541.         unixContext.sc_psr = machStatePtr->trapRegs->curPsr;
  1542.         unixContext.sc_g1 = machStatePtr->trapRegs->globals[1];
  1543.         unixContext.sc_o0 = machStatePtr->trapRegs->ins[0];
  1544.         /*
  1545.          * machContext.pcValue is the address of the handler.
  1546.          */
  1547.         machStatePtr->trapRegs->pc = (unsigned int)
  1548.             machStatePtr->sigContext.  machContext.pcValue;
  1549.         machStatePtr->trapRegs->nextPc = (unsigned int)
  1550.             machStatePtr->sigContext.machContext.pcValue+4;
  1551.         if (debugProcStubs) {
  1552.         printf("new pc = %x\n", machStatePtr->trapRegs->nextPc);
  1553.         }
  1554.         /*
  1555.          * Copy the window to the signal stack.
  1556.          */
  1557.         Vm_CopyIn(16*sizeof(int), (Address)unixContext.sc_sp, (Address)n);
  1558.         if (debugProcStubs) {
  1559.         printf("Regs: %x %x %x, %x %x %x\n", n[0], n[1], n[2], n[8],
  1560.             n[9], n[10]);
  1561.         }
  1562.         machStatePtr->trapRegs->ins[6] += MACH_SAVED_WINDOW_SIZE;
  1563.         unixContext.sc_wbcnt = 0;
  1564.         sigStackPtr->contextPtr = (Sig_Context *)
  1565.             (unixContext.sc_sp-sizeof(struct sigcontext));
  1566.         if (Vm_CopyOut(MACH_SAVED_WINDOW_SIZE,
  1567.             (Address)n,
  1568.             (Address)unixContext.sc_sp - sizeof(struct sigcontext)
  1569.                 - 4*sizeof(int) - MACH_SAVED_WINDOW_SIZE) !=
  1570.                 SUCCESS) {
  1571.         return 0;
  1572.         }
  1573.         if (debugProcStubs) {
  1574.         printf("Copied window to %x\n",
  1575.             (Address)unixContext.sc_sp - sizeof(struct sigcontext)
  1576.                 - 4*sizeof(int) - MACH_SAVED_WINDOW_SIZE);
  1577.         }
  1578.         /*
  1579.          * Copy the sigStack and sigContext to the signal window.
  1580.          */
  1581.         if (Vm_CopyOut(4*sizeof(int), (Address)sigStackPtr,
  1582.             (Address)unixContext.sc_sp - sizeof(struct sigcontext)
  1583.                 - 4*sizeof(int)) != SUCCESS) {
  1584.         return 0;
  1585.         }
  1586.         if (Vm_CopyOut(sizeof(struct sigcontext), (Address)&unixContext,
  1587.             (Address)unixContext.sc_sp - sizeof(struct sigcontext))
  1588.                 != SUCCESS) {
  1589.         return 0;
  1590.         }
  1591.         return 2;
  1592.     } else {
  1593.         return 1;
  1594.     }
  1595.     } else {
  1596.     if (procPtr->unixProgress == PROC_PROGRESS_MIG_RESTART ||
  1597.                     procPtr->unixProgress == PROC_PROGRESS_RESTART) {
  1598.         restarted = 1;
  1599.         if (debugProcStubs) {
  1600.         printf("No signal action, so we restarted call\n");
  1601.         }
  1602.         procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1603.     } else if (restarted) {
  1604.         printf("No signal, yet we restarted system call!\n");
  1605.     }
  1606.     }
  1607.     if (machStatePtr->fpuStatus & MACH_FPU_EXCEPTION_PENDING) {
  1608.     HandleFPUException(procPtr, machStatePtr);
  1609.     }
  1610.     /*
  1611.      * It is possible for Sig_Handle to mask the migration signal
  1612.      * if a process is not in a state where it can be migrated.
  1613.      * As soon as we return to user mode, though, we will allow migration.
  1614.      * Clear the bit anytime something's pending, for simplicity.
  1615.      */
  1616.     if (procPtr->sigPendingMask) {
  1617.     Sig_AllowMigration(procPtr);
  1618.     }
  1619.  
  1620.     if (restarted) {
  1621.     if (debugProcStubs) {
  1622.         printf("Moving PC to restart system call (no signal\n");
  1623.     }
  1624.     machStatePtr->trapRegs->nextPc = machStatePtr->trapRegs->pc;
  1625.     machStatePtr->trapRegs->pc = machStatePtr->trapRegs->nextPc-4;
  1626.     /*
  1627.      * We need to restore %o0 which got clobbered by
  1628.      * the system call.
  1629.      */
  1630.     machStatePtr->trapRegs->ins[0] = machStatePtr->savedArgI0;
  1631.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1632.     }
  1633.  
  1634.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1635.             procPtr->unixProgress != PROC_PROGRESS_UNIX && debugProcStubs) {
  1636.         printf("UnixProgress = %d leaving MachUserReturn\n",
  1637.         procPtr->unixProgress);
  1638.     }
  1639.  
  1640.     /*
  1641.      * Go back to MachReturnFromTrap.  We are expected to have interrupts
  1642.      * off there.
  1643.      */
  1644.     Mach_DisableIntr();
  1645.     
  1646.     return 0;
  1647. }
  1648.  
  1649.  
  1650. /*
  1651.  *----------------------------------------------------------------------
  1652.  *
  1653.  * MachHandleTrap --
  1654.  *
  1655.  *    Handle an instruction trap, such as an illegal instruction trap,
  1656.  *    an unaligned address, or a floating point problem.
  1657.  *
  1658.  * Results:
  1659.  *    None.
  1660.  *
  1661.  * Side effects:
  1662.  *    If it occured in the kernel, we panic.  If it occured in a user
  1663.  *    program, we take appropriate signal action.
  1664.  *
  1665.  *----------------------------------------------------------------------
  1666.  */
  1667. void
  1668. MachHandleTrap(trapType, pcValue, trapPsr)
  1669.     int            trapType;
  1670.     Address        pcValue;
  1671.     unsigned    int    trapPsr;
  1672. {
  1673.     Proc_ControlBlock    *procPtr;
  1674.  
  1675.     /*
  1676.      * Find the current process.  If we took a MACH_FP_EXCEP at one of the
  1677.      * marked FPU sync instructions, then we use the process saved
  1678.      * in machFPUSaveProcPtr.
  1679.      */
  1680.     procPtr = ((trapType == MACH_FP_EXCEP) && 
  1681.            (pcValue == (Address) &machFPUSyncInst)) ?
  1682.            machFPUSaveProcPtr : Proc_GetCurrentProc();
  1683.     if ((procPtr == (Proc_ControlBlock *) NIL)) {
  1684.         printf("%s: pc = 0x%x, trapType = %d\n",
  1685.         "MachHandleTrap", pcValue, trapType);
  1686.         panic("Current process was NIL!\n");
  1687.     }
  1688.     /*
  1689.      * Handle kernel-mode traps.
  1690.      */
  1691.     if (trapPsr & MACH_PS_BIT) {
  1692.     switch (trapType) {
  1693.     case MACH_ILLEGAL_INSTR:
  1694.         printf("%s %s\n", "MachHandleTrap: illegal",
  1695.             "instruction trap in the kernel!");
  1696.         break;
  1697.     case MACH_PRIV_INSTR:
  1698.         printf("%s %s\n", "MachHandleTrap: privileged",
  1699.             "instruction trap in the kernel!");
  1700.         break;
  1701.     case MACH_MEM_ADDR_ALIGN:
  1702.         printf("%s %s\n", "MachHandleTrap: unaligned",
  1703.             "address trap in the kernel!");
  1704.         break;
  1705.     case MACH_TAG_OVERFLOW:
  1706.         printf("%s %s\n", "MachHandleTrap: tag",
  1707.             "overflow trap in the kernel!");
  1708.         break;
  1709.     case MACH_FP_EXCEP: {
  1710.         /*
  1711.          * We got a FP execption while running in kernel mode. If this
  1712.          * exception occured at a known location we clear the
  1713.          * exception and mark the Mach_State.
  1714.          */
  1715.         if (pcValue == (Address) &machFPUDumpSyncInst) {
  1716.         /*
  1717.          * Already doing a MachFPUDumpState.  Whoever's doing the
  1718.          * dump should check the pending flag and set fpuStatus if
  1719.          * it's set.
  1720.          */
  1721.         procPtr->machStatePtr->fpuStatus |=
  1722.             MACH_FPU_EXCEPTION_PENDING;
  1723.         return;
  1724.         }
  1725.         if (pcValue == (Address) &machFPUSyncInst) {
  1726.           MachFPUDumpState(procPtr->machStatePtr->trapRegs);
  1727.           procPtr->machStatePtr->fpuStatus |= 
  1728.               (procPtr->machStatePtr->trapRegs->fsr
  1729.                     & MACH_FSR_TRAP_TYPE_MASK) |
  1730.               MACH_FPU_EXCEPTION_PENDING;
  1731.           procPtr->specialHandling = 1;
  1732.           return;
  1733.         } 
  1734.         printf("%s. ",
  1735.     "MachHandleTrap: FPU exception from kernel process.");
  1736.         break;
  1737.     }
  1738.     case MACH_FP_DISABLED:
  1739.         printf("%s %s\n", "MachHandleTrap: fp unit",
  1740.             "disabled trap in the kernel!");
  1741.         break;
  1742.     default:
  1743.         printf("%s %s\n", "MachHandleTrap: hit default",
  1744.             "in case statement - bad trap instruction called us!");
  1745.         break;
  1746.     }
  1747.     panic("%s %s %s %x %s %x\n",
  1748.         "MachHandleTrap: the error occured in a",
  1749.         procPtr->genFlags & PROC_USER ? "user" : "kernel",
  1750.         "process, with procPtr =", (unsigned int) procPtr,
  1751.         "and pc =", pcValue);
  1752.     }
  1753.     /*
  1754.      * The trap occured in user-mode.
  1755.      */
  1756.     switch (trapType) {
  1757.     case MACH_ILLEGAL_INSTR:
  1758.     (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE, procPtr->processID,
  1759.         FALSE, pcValue);
  1760.     break;
  1761.     case MACH_PRIV_INSTR:
  1762.     (void) Sig_Send(SIG_ILL_INST, SIG_PRIV_INST, procPtr->processID,
  1763.         FALSE, pcValue);
  1764.     break;
  1765.     case MACH_MEM_ADDR_ALIGN:
  1766.     (void) Sig_Send(SIG_ADDR_FAULT, SIG_ADDR_ERROR, procPtr->processID,
  1767.         FALSE, (Address)0);
  1768.     break;
  1769.     case MACH_FP_EXCEP: {
  1770.          unsigned int fsr;
  1771.      /*
  1772.       * An FP exception from user mode.  Clear the exception and 
  1773.       * mark it in the Mach_State struct.  
  1774.       * 
  1775.       */
  1776.      MachFPUDumpState(procPtr->machStatePtr->trapRegs);
  1777.      fsr = procPtr->machStatePtr->trapRegs->fsr;
  1778.      if (!(procPtr->machStatePtr->fpuStatus & MACH_FPU_ACTIVE)) {
  1779.          printf(
  1780. "FPU exception from process without MACH_FPU_ACTIVE, fsr = 0x%x\n",fsr);
  1781.      }
  1782.      procPtr->machStatePtr->fpuStatus |= (fsr & MACH_FSR_TRAP_TYPE_MASK) |
  1783.                         MACH_FPU_EXCEPTION_PENDING;
  1784.      procPtr->specialHandling = 1;
  1785.      break;
  1786.     }
  1787.     case MACH_FP_DISABLED: {
  1788.     register Mach_State     *machStatePtr;
  1789.  
  1790.     Mach_FlushWindowsToStack();
  1791.     machStatePtr = procPtr->machStatePtr;
  1792.     /*
  1793.      * Upon a user's first FPU disable trap we initialize and enable
  1794.      * the FPU for him. 
  1795.      */
  1796.     if (machStatePtr->fpuStatus & MACH_FPU_ACTIVE) {
  1797.         panic("Double FPU_DISABLE trap.\n");
  1798.     }
  1799.     machStatePtr->fpuStatus = MACH_FPU_ACTIVE;
  1800.     /*
  1801.      * Enable the FPU in the trap PSR.
  1802.      */
  1803.     machStatePtr->trapRegs->curPsr |= MACH_ENABLE_FPP;
  1804.     /*
  1805.      * Initialize the FPU registers. 
  1806.      */
  1807.     machStatePtr->trapRegs->fsr = 0;
  1808.     bzero((Address) (machStatePtr->trapRegs->fregs), MACH_NUM_FPS*4);
  1809.     MachFPULoadState(machStatePtr->trapRegs);
  1810.     break;
  1811.     }
  1812.     case MACH_TAG_OVERFLOW:
  1813.     panic("%s %s\n", "MachHandleTrap: tag",
  1814.         "overflow trap in user process, but I don't deal with it yet.");
  1815.     break;
  1816.     default:
  1817.     panic("%s %s\n", "MachHandleTrap: hit default",
  1818.         "in case statement - bad trap instruction from user mode.");
  1819.     break;
  1820.  
  1821.     }
  1822.     return;
  1823. }
  1824.  
  1825.  
  1826. /*
  1827.  *----------------------------------------------------------------------
  1828.  *
  1829.  * FlushTheWindows --
  1830.  *
  1831.  *    A recursive C routine that will force window overflows and thereby
  1832.  *    flush the register windows to the stack.
  1833.  *
  1834.  * Results:
  1835.  *    None.
  1836.  *
  1837.  * Side effects:
  1838.  *    The register windows are flushed.
  1839.  *
  1840.  *----------------------------------------------------------------------
  1841.  */
  1842. static void
  1843. FlushTheWindows(num)
  1844.     int    num; 
  1845. {
  1846.     num--;
  1847.     if (num > 0) {
  1848.     FlushTheWindows(num);
  1849.     }
  1850.     return;
  1851. }
  1852.  
  1853.  
  1854. /*
  1855.  *----------------------------------------------------------------------
  1856.  *
  1857.  * Mach_FlushWindowsToStack --
  1858.  *
  1859.  *    Calls a routine to flush the register windows to the stack.
  1860.  *    This routine can be caled from traps, or wherever.
  1861.  *
  1862.  * Results:
  1863.  *    None.
  1864.  *
  1865.  * Side effects:
  1866.  *    The register windows are flushed.
  1867.  *
  1868.  *----------------------------------------------------------------------
  1869.  */
  1870. void
  1871. Mach_FlushWindowsToStack()
  1872. {
  1873.     /*
  1874.      * We want to do NWINDOWS - 1 saves and then restores to make sure all our
  1875.      * register windows have been saved to the stack.  Calling here does one
  1876.      * save, so we want to do NWINDOWS - 2 more calls and returns.
  1877.      */
  1878.     FlushTheWindows(MACH_NUM_WINDOWS - 2);
  1879.     return;
  1880. }
  1881.  
  1882.  
  1883. /*
  1884.  *----------------------------------------------------------------------
  1885.  *
  1886.  * MachUserDebug --
  1887.  *
  1888.  *    This will cause the current process to go into the debugger.  It can
  1889.  *    be called from trap handlers, etc.  It first checks to see if the
  1890.  *    current process is NIL.
  1891.  *
  1892.  * Results:
  1893.  *    None.
  1894.  *
  1895.  * Side effects:
  1896.  *    The process gets a breakpoint signal.
  1897.  *
  1898.  *----------------------------------------------------------------------
  1899.  */
  1900. void
  1901. MachUserDebug()
  1902. {
  1903.     Proc_ControlBlock    *procPtr; 
  1904.  
  1905.     procPtr = Proc_GetCurrentProc();
  1906.     if (procPtr == (Proc_ControlBlock *) NIL) {
  1907.     panic("MachUserDebug: current process was NIL!\n");
  1908.     }
  1909.     Sig_Send(SIG_BREAKPOINT, SIG_NO_CODE, procPtr->processID, FALSE,
  1910.         (Address)0);
  1911.     return;
  1912. }
  1913.  
  1914.  
  1915. /*
  1916.  *----------------------------------------------------------------------
  1917.  *
  1918.  * Mach_GetBootArgs --
  1919.  *
  1920.  *    Returns the arguments out of the boot parameter structure. 
  1921.  *
  1922.  * Results:
  1923.  *    Number of elements returned in argv.
  1924.  *
  1925.  * Side effects:
  1926.  *    None.
  1927.  *
  1928.  *----------------------------------------------------------------------
  1929.  */
  1930.  
  1931. int
  1932. Mach_GetBootArgs(argc, bufferSize, argv, buffer)
  1933.     int    argc;            /* Number of elements in argv */
  1934.     int    bufferSize;        /* Size of buffer */
  1935.     char    **argv;            /* Ptr to array of arg pointers */
  1936.     char    *buffer;        /* Storage for arguments */
  1937. {
  1938.     int        i;
  1939.     int        offset;
  1940.  
  1941.     bcopy(machMonBootParam.strings, buffer, 
  1942.       (bufferSize < 100) ? bufferSize : 100);
  1943.     offset = (unsigned int) machMonBootParam.strings - (unsigned int) buffer;
  1944.     for(i = 0; i < argc; i++) {
  1945.     if (machMonBootParam.argPtr[i] == (char *) 0 ||
  1946.         machMonBootParam.argPtr[i] == (char *) NIL) {
  1947.         break;
  1948.     }
  1949.     argv[i] = (char *) (machMonBootParam.argPtr[i] - (char *) offset);
  1950.     }
  1951.     return i;
  1952. }
  1953.  
  1954.  
  1955. /*
  1956.  *----------------------------------------------------------------------
  1957.  *
  1958.  * Mach_GetStackPointer --
  1959.  *
  1960.  *    This is a stub routine for the sun4.
  1961.  *
  1962.  * Results:
  1963.  *    Address.
  1964.  *
  1965.  * Side effects:
  1966.  *    It panics since it should never be called.  If it ends up being
  1967.  *    useful someday, change it so it doesn't panic.
  1968.  *
  1969.  *----------------------------------------------------------------------
  1970.  */
  1971. Address
  1972. Mach_GetStackPointer()
  1973. {
  1974.     panic("Mach_GetStackPointer");
  1975.     return NULL;
  1976. }
  1977.  
  1978. /*
  1979.  *----------------------------------------------------------------------
  1980.  *
  1981.  * HandleFPUException --
  1982.  *
  1983.  *    Handle any FPU exception present.
  1984.  *
  1985.  * Results:
  1986.  *    None.
  1987.  *
  1988.  * Side effects:
  1989.  *    FPU instruction emulated, process may be sent signal.
  1990.  *
  1991.  *----------------------------------------------------------------------
  1992.  */
  1993.  
  1994. static void
  1995. HandleFPUException(procPtr, machStatePtr)
  1996.     Proc_ControlBlock *procPtr;    /* Process control block of offending process*/
  1997.     Mach_State     *machStatePtr;  /* Machine state of process. */
  1998. {    
  1999.     int        i;
  2000.     Mach_RegWindow    *curWindow;
  2001.  
  2002.     switch (machStatePtr->fpuStatus & MACH_FSR_TRAP_TYPE_MASK) {
  2003.     case    MACH_FSR_IEEE_TRAP:
  2004.     case    MACH_FSR_UNFINISH_TRAP:
  2005.     case    MACH_FSR_UNIMPLEMENT_TRAP:
  2006.         break;
  2007.     case    MACH_FSR_SEQ_ERRROR_TRAP: {
  2008.         panic("Floating point sequence error, fsr = 0x%x\n",
  2009.          machStatePtr->trapRegs->fsr);
  2010.         break;
  2011.     }
  2012.     case    MACH_FSR_NO_TRAP:
  2013.     default: {
  2014.         panic("Floating point exception with bad trap code, fsr = 0x%x\n", 
  2015.             machStatePtr->trapRegs->fsr);
  2016.         break;
  2017.     }
  2018.     }
  2019.     machStatePtr->fpuStatus &= 
  2020.         ~(MACH_FPU_EXCEPTION_PENDING|MACH_FSR_TRAP_TYPE_MASK);
  2021.     /*
  2022.      * Emulate the evil instructions, and restore the result into the FPU.
  2023.      */
  2024.     curWindow = (Mach_RegWindow *)
  2025.         (machStatePtr->trapRegs->ins[MACH_FP_REG]);
  2026.     for (i = 0; i < machStatePtr->trapRegs->numQueueEntries; i++) {
  2027.     MachFPU_Emulate(procPtr->processID, 
  2028.             machStatePtr->trapRegs->fqueue[i].address,
  2029.             machStatePtr->trapRegs,
  2030.             curWindow);
  2031.     }
  2032.     MachFPULoadState(machStatePtr->trapRegs);
  2033.  
  2034. }
  2035. /*
  2036.  *----------------------------------------------------------------------
  2037.  *
  2038.  * Mach_SigreturnStub --
  2039.  *
  2040.  *    Return from a unix signal or long jump.
  2041.  *
  2042.  * Results:
  2043.  *    None.
  2044.  *
  2045.  * Side effects:
  2046.  *    Changes control of execution.
  2047.  *
  2048.  *----------------------------------------------------------------------
  2049.  */
  2050. int
  2051. Mach_SigreturnStub(jmpBuf)
  2052. jmp_buf *jmpBuf;
  2053. {
  2054.     struct sigcontext context;
  2055.     Proc_ControlBlock    *procPtr = Proc_GetCurrentProc();
  2056.     Mach_State        *machStatePtr = procPtr->machStatePtr;
  2057.  
  2058.     if (Vm_CopyIn(9*sizeof(int), (Address)jmpBuf, (Address)&context) !=
  2059.         SUCCESS) {
  2060.     printf("jmp_buf copy in failure\n");
  2061.     return -1;
  2062.     }
  2063.     if (debugProcStubs) {
  2064.     printf("Unix sigreturn: pc = %x, sp = %x, psr = %x\n", context.sc_pc,
  2065.         context.sc_sp, context.sc_psr&MACH_DISABLE_TRAP_BIT &
  2066.         ~MACH_PS_BIT);
  2067.     }
  2068.     machStatePtr->trapRegs->pc = context.sc_pc;
  2069.     machStatePtr->trapRegs->nextPc = context.sc_npc;
  2070.  
  2071.     machStatePtr->trapRegs->globals[1] = context.sc_g1;
  2072.     machStatePtr->trapRegs->ins[0] = context.sc_o0;
  2073.     machStatePtr->sigContext.oldHoldMask = context.sc_mask;
  2074.     machStatePtr->trapRegs->curPsr = (machStatePtr->trapRegs->curPsr&
  2075.         ~MACH_PSR_SIG_RESTORE) | (context.sc_psr&MACH_PSR_SIG_RESTORE);
  2076.     machStatePtr->trapRegs->ins[6] = context.sc_sp;
  2077.     Sig_Return(procPtr, &machStatePtr->sigStack);
  2078.     return 0; /* Dummy */
  2079. }
  2080.